/**
 * @class   TaskManagerImpl
 * @brief   
 *
 *
 *
 *
 *
 ****************************************************************************
 * @version $Id: TaskManagerImpl.h 2051 2010-03-07 08:27:48Z alex $
 * @author  Alessandro Polo
 ****************************************************************************/
/* Copyright (c) 2007-2010, WOSH - Wide Open Smart Home 
 * by Alessandro Polo - OpenSmartHome.com
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the OpenSmartHome.com WOSH nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY Alessandro Polo ''AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL Alessandro Polo BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ****************************************************************************/

#ifndef __WOSH_Services_TaskManagerImpl_H__
 #define __WOSH_Services_TaskManagerImpl_H__

 #include <core/BundleGenericWorker.h>
 #include <core/Containers.h>
 #include <core/Utilities.h>
 #include <core/Message.h>
 #include <core/ThreadPool.h>
 #include <queue>

 #include <framework/automations/Automation.h>
 #include <framework/xtended/Metronome.h>


class TaskManagerImpl;

using namespace wosh;
using namespace wosh::automations;


class ScheduledTask
 {
	public:
		ScheduledTask( Message* message, int64 time )
			: timeTick(time), message(message), priority(0) { }
		~ScheduledTask() {
			if ( message != NULL )
				delete message;
		 }
	public:
		void addTask( Automation* task ) {
			if ( task == NULL ) return;
			this->priority += task->getPriority();
			this->tasks.push_back(task);
		 }

	public:
		int64 timeTick;
		Message* message;
		long priority;

		std::vector<Automation*> tasks;

};

struct ScheduledTaskPriorityComparison {
	bool operator()(ScheduledTask *x, ScheduledTask *y) {
		if ( x == NULL ) return false;
		if ( y == NULL ) return true;
		return x->priority > y->priority;
	 }
};

class ScheduledTaskExecuter : public ThreadMethod
 {
	public:
		ScheduledTaskExecuter( TaskManagerImpl* parent_ptr )
			: ThreadMethod(NULL, "ScheduledTaskExecuter"), parent(parent_ptr), task(NULL) { }

		virtual ~ScheduledTaskExecuter() { }

	public:
		void setTask( ScheduledTask* task_ptr ) {
			MutexLockerWrite mL(&this->processingLock);
			this->task = task_ptr;
		 }

		void crashDetected( double probability );

	public:
		virtual void work();

	protected:
		TaskManagerImpl* parent;				///< my parent coordinator
		ScheduledTask* task;

};


typedef List22<Automation*> tAutomationList;



class TaskManagerImpl :	public BundleGenericWorker,
						public wosh::xtended::IMetronomeListener
 {

	public:

	public:

		/**
		 * @brief   Default constructor. Init vars.
		 */
		TaskManagerImpl( BundleGeneric& bundle );

		/**
		 * @brief   Deconstructor. If thread is stll running, it will be stopped.
		 */
		virtual ~TaskManagerImpl();


	public:


		inline void tickEvent( int64 time, wosh::xtended::Metronome* ) {
			evalEvent( time, NULL );
		 }

		inline void busMessage( const Message& message, const Bus* ) {
			evalEvent( Utilities::std_time(), &message );
		 }

		void evalEvent( int64 time, const Message* message );


		void scheduleTask( ScheduledTask* newTask );

/** @name Setters
 * @{
 ******************************************************************************/
	public:

//@}
/** @name Getters
 * @{
 ******************************************************************************/
	public:

		const tAutomationList& getAutomations() const	{ return this->automations; }
		tAutomationList& getAutomations()				{ return this->automations; }

	

//@}
/** @name Internal methods
 * @{
 ******************************************************************************/
	protected:
		/**
		 * @brief   
		 * @see     running
		 * @see     
		 */
		void runThread();

		bool initializingThread();
		void exitingThread();

		void evalEvent( ScheduledTask* task );

//@}
	protected:
		std::priority_queue<ScheduledTask*,
							std::vector<ScheduledTask*>,
							ScheduledTaskPriorityComparison> queueTask;	///< task' queue
		Mutex queueMux;

		tAutomationList automations;

		wosh::xtended::Metronome clock;

		ThreadPool<ScheduledTaskExecuter>* workersPool;			///< collection of worker processes

		friend class ScheduledTaskExecuter;

}; // class def


#endif //__WOSH_Services_TaskManagerImpl_H__
